package com.yangyang.lamviarm.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.yangyang.lamviarm.entity.JActionDef;
import com.yangyang.lamviarm.entity.JActionModelDef;
import com.yangyang.lamviarm.entity.JPredicate;
import com.yangyang.lamviarm.entity.JPredicateDef;
import com.yangyang.lamviarm.server.entity.JObject;
import com.yangyang.lamviarm.server.entity.JRobot;

public class JSimulator {

	private static JRobot robot; // ������
	public static List<JPredicate> currentstate; // ��ǰ״̬����
	public static List<JPredicate> goalstate; // Ŀ��״̬����
	public static JSimulator simulator = new JSimulator();

	static class StateGoalStorage {
		private static List<List<JPredicate>> states = new ArrayList<List<JPredicate>>();
		private static List<List<JPredicate>> goals = new ArrayList<List<JPredicate>>();
		private static int mPtr = 0;

		public static void addStates(List<JPredicate> state) {
			states.add(state);
		}

		public static void addGoals(List<JPredicate> goal) {
			goals.add(goal);
		}

		public static boolean movePtr() {
			boolean result = states.size() == goals.size()
					&& states.size() > mPtr;
			if (result) {
				currentstate = states.get(mPtr);
				goalstate = goals.get(mPtr++);
			}
			return result;
		}
	}

	public static boolean movePtr() {
		return StateGoalStorage.movePtr();
	}

	public JSimulator() {
		JSimulator.currentstate = new ArrayList<JPredicate>();
		JSimulator.goalstate = new ArrayList<JPredicate>();
	}

	/* ��ȡ���ڵ�actionmodel���µ�ǰ״̬ */
	public boolean updateStatus(JActionModelDef model,
			HashMap<String, String> mapVariableValue) {
		for (String strPre : model.mEffectD) {
			JPredicate pre = JPredicate.parseByVar(strPre, mapVariableValue,
					JSimulator.currentstate);
			assert (JSimulator.currentstate.contains(pre));
			currentstate.remove(pre);
		}
		for (String strPre : model.mEffectA) {
			JPredicate pre = JPredicate.parseByVar(strPre, mapVariableValue,
					JSimulator.currentstate);
			if (!currentstate.contains(pre))
				currentstate.add(pre);
		}
		return true;
	}

	public boolean rightAction(String line,
			HashMap<String, String> mapVariableValue) {
		String[] array = line.split("_");
		JActionModelDef model = JActionModelDef.mapNameActionModel
				.get(array[0]);
		if (model == null) {
			System.err.println("action model undefined!");
			assert (false);
			return false;
		} else {
			List<String> precondition = model.mPrecondition; //
			List<String> variable = model.mActionVariable;
			mapVariableValue.clear();
			for (int i = 0; i < variable.size(); i++) {
				mapVariableValue.put(variable.get(i), (String) array[i + 1]);
			}
			for (String predicate : precondition) {
				if (!JPredicate.predicateCorrect(predicate, mapVariableValue,
						JSimulator.currentstate))
					return false;
			}
			return true;
		}
	}

	public boolean doAction(String line) {

		HashMap<String, String> mapVariableValue = new HashMap<String, String>();
		if (!rightAction(line, mapVariableValue)) {
			return false;
		}

		String[] array = line.split("_");
		JActionModelDef model = JActionModelDef.mapNameActionModel
				.get(array[0]);
		if (array[0].equals("move"))
			robot.setPosition(Integer.parseInt(array[2].toString()));
		return updateStatus(model, mapVariableValue);
	}

	public static void addObjectType(String name) {
		JObject.addObjectType(name);
	}

	/* ����µ����� */
	public static void addObject(List<String> line) {
		for (int i = 1; i < line.size(); i++) {
			if (line.get(0).equals("robot")) {
				robot = new JRobot(line.get(0), line.get(i), -1);
			} else {
				new JObject(line.get(0), line.get(i), -1);
			}

		}
	}

	public static void addPredicateDef(List<String> line) {
		new JPredicateDef(line);
	}

	public static void addActionDef(List<String> line) {
		new JActionDef(line);
	}

	public static void addActionModelDef(String action, String precondition,
			String effecta, String effectd) {
		List<String> formatedAction = new ArrayList<String>();
		List<String> formatedPrecondition = new ArrayList<String>();
		List<String> formatedEffectA = new ArrayList<String>();
		List<String> formatedEffectD = new ArrayList<String>();
		String[] array = action.split("_");
		for (int i = 0; i < array.length; i++)
			formatedAction.add(array[i]);
		array = precondition.split(":");
		for (int i = 1; i < array.length; i++)
			formatedPrecondition.add(array[i]);
		array = effecta.split(":");
		for (int i = 1; i < array.length; i++)
			formatedEffectA.add(array[i]);
		array = effectd.split(":");
		for (int i = 1; i < array.length; i++)
			formatedEffectD.add(array[i]);
		new JActionModelDef(formatedAction, formatedPrecondition,
				formatedEffectA, formatedEffectD);
	}

	public static void endAddState() {
		if (currentstate.size() > 0) {
			StateGoalStorage.addStates(currentstate);
			currentstate = new ArrayList<JPredicate>();
		}
		if (goalstate.size() > 0)
			StateGoalStorage.addGoals(goalstate);
		goalstate = new ArrayList<JPredicate>();
	}

	public static void addState(int type, String predicate) {
		switch (type) {
		case 1:
			JPredicate pre = JPredicate.parsePredicate(predicate);
			if (pre != null) {
				currentstate.add(pre);
				if (pre.getName().equals("location")
						&& pre.getParams()[0].equals(robot.getName())) {
					robot.setPosition(Integer.parseInt(pre.getParams()[1]
							.toString()));
				}
			}

			break;
		case 2:
			goalstate.add(JPredicate.parsePredicate(predicate));
			break;
		case 3:
			String[] array = predicate.split("_");
			List<String> line = new ArrayList<String>();
			for (int i = 0; i < array.length; i++) {
				line.add(array[i]);
			}
			JSimulator.addObject(line);
			break;
		default:
			System.err.println("undefined state:" + type + "\npredicate:"
					+ predicate);
			break;
		}
	}

	public String toString(String txtMask) {
		StringBuilder sb = new StringBuilder();
		sb.append("==\n==\n");

		if (txtMask.charAt(0) != '0') {
			sb.append("robot info:" + robot);
		}
		if (txtMask.charAt(1) != '0') {
			sb.append("==object info== \n");
			for (JObject obj : JObject.mapNameInstance.values())
				sb.append("\t" + obj);
			sb.append("==object info== \n");
		}

		if (txtMask.charAt(2) != '0') {
			sb.append("==current state info== \n");
			for (JPredicate obj : currentstate)
				sb.append("\t" + obj + "\n");
			sb.append("==current state info== \n");
		}
		if (txtMask.charAt(3) != '0') {
			sb.append("==goal state info== \n");
			for (JPredicate obj : goalstate)
				sb.append("\t" + obj + "\n");
			sb.append("==goal state info== \n");
		}
		if (txtMask.charAt(4) != '0') {
			sb.append("==predicate def info== \n");
			for (JPredicateDef obj : JPredicateDef.mapNamePredicate.values())
				sb.append("\t" + obj + "\n");
			sb.append("==predicate def info== \n");
		}
		if (txtMask.charAt(5) != '0') {
			sb.append("==action def info== \n");
			for (JActionDef obj : JActionDef.mapNameActionDef.values())
				sb.append("\t" + obj + "\n");
			sb.append("==action def info== \n");
		}
		if (txtMask.charAt(6) != '0') {
			sb.append("==actionmodel def info== \n");
			for (JActionModelDef obj : JActionModelDef.mapNameActionModel
					.values())
				sb.append("\t" + obj + "\n");
			sb.append("==actionmodel def info== \n");
		}

		sb.append("\n==\n==\n");
		return sb.toString();
	}

	public static List<JPredicate> Observation() {
		List<JPredicate> result = new ArrayList<JPredicate>();
		result.addAll(currentstate);
		int position = robot.getPosition();
		if (position / 1000 < 6) {
			List<String> list = new ArrayList<String>();
			list.add("near");
			list.add("" + position);
			list.add("" + (position + 1000));
			result.add(new JPredicate(list));
		}
		if (position / 1000 > 2) {
			List<String> list = new ArrayList<String>();
			list.add("near");
			list.add("" + position);
			list.add("" + (position - 1000));
			result.add(new JPredicate(list));
		}
		if (position % 1000 < 6) {
			List<String> list = new ArrayList<String>();
			list.add("near");
			list.add("" + position);
			list.add("" + (position + 1));
			result.add(new JPredicate(list));
		}
		if (position % 1000 > 2) {
			List<String> list = new ArrayList<String>();
			list.add("near");
			list.add("" + position);
			list.add("" + (position - 1));
			result.add(new JPredicate(list));
		}
		return result;
	}

	public static void printInfo() {
		System.out.println("==\n==\n");

		System.out.println("robot info:" + robot);
		System.out.println("==object info== ");
		for (JObject obj : JObject.mapNameInstance.values())
			System.out.println("\t" + obj);
		System.out.println("==object info== ");

		System.out.println("==current state info== ");
		for (JPredicate obj : currentstate)
			System.out.println("\t" + obj);
		System.out.println("==current state info== ");

		System.out.println("==goal state info== ");
		for (JPredicate obj : goalstate)
			System.out.println("\t" + obj);
		System.out.println("==goal state info== ");

		System.out.println("==predicate def info== ");
		for (JPredicateDef obj : JPredicateDef.mapNamePredicate.values())
			System.out.println("\t" + obj);
		System.out.println("==predicate def info== ");

		System.out.println("==action def info== ");
		for (JActionDef obj : JActionDef.mapNameActionDef.values())
			System.out.println("\t" + obj);
		System.out.println("==action def info== ");

		System.out.println("==actionmodel def info== ");
		for (JActionModelDef obj : JActionModelDef.mapNameActionModel.values())
			System.out.println("\t" + obj);
		System.out.println("==actionmodel def info== ");

		System.out.println("\n==\n==\n");
	}
}
